import element.base.Word;
import element.synt.Program;
import symbol.astPreprocessContext;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.GroupLayout;
/*
 * Created by JFormDesigner on Fri Dec 15 19:33:05 CST 2023
 */



/**
 * @author moc85
 */
public class WindowsFrame extends JFrame {
    public WindowsFrame() {
        initComponents();
    }

    private void initComponents() {
        // JFormDesigner - Component initialization - DO NOT MODIFY  //GEN-BEGIN:initComponents  @formatter:off
        // Generated using JFormDesigner Evaluation license - Wenchong Xu
        scrollPane1 = new JScrollPane();
        TextArea = new JTextArea();
        scrollPane2 = new JScrollPane();
        Ccode = new JTextArea();
        button2 = new JButton();
        button3 = new JButton();
        scrollPane3 = new JScrollPane();
        Result = new JTextArea();

        //======== this ========
        setBackground(new Color(0x00ccff));
        setTitle("Kill Fucking C");
        var contentPane = getContentPane();

        //======== scrollPane1 ========
        {

            //---- TextArea ----
            TextArea.setFont(new Font("Consolas", Font.PLAIN, 20));
            TextArea.setTabSize(4);
            TextArea.setLineWrap(true);
            scrollPane1.setViewportView(TextArea);
        }

        //======== scrollPane2 ========
        {

            //---- Ccode ----
            Ccode.setEditable(false);
            Ccode.setFont(new Font("Consolas", Font.PLAIN, 20));
            Ccode.setTabSize(4);
            Ccode.setLineWrap(true);
            scrollPane2.setViewportView(Ccode);
        }

        //---- button2 ----
        button2.setText("\u7f16\u8bd1");
        button2.setFont(new Font("\u5fae\u8f6f\u96c5\u9ed1", Font.PLAIN, 13));

        button2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try{
                    Parse();
                } catch (IOException exc) {

                }
            }
        });

        //---- button3 ----
        button3.setText("\u8fd0\u884c");
        button3.setFont(new Font("\u5fae\u8f6f\u96c5\u9ed1", Font.PLAIN, 13));

        button3.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                compileWithGCC();
                executeExecutable();
            }
        });

        //======== scrollPane3 ========
        {

            //---- Result ----
            Result.setFont(new Font("Consolas", Font.BOLD, 20));
            Result.setTabSize(4);
            scrollPane3.setViewportView(Result);
        }

        GroupLayout contentPaneLayout = new GroupLayout(contentPane);
        contentPane.setLayout(contentPaneLayout);
        contentPaneLayout.setHorizontalGroup(
            contentPaneLayout.createParallelGroup()
                .addGroup(contentPaneLayout.createSequentialGroup()
                    .addGap(12, 12, 12)
                    .addGroup(contentPaneLayout.createParallelGroup()
                        .addComponent(scrollPane3)
                        .addGroup(contentPaneLayout.createSequentialGroup()
                            .addComponent(scrollPane1, GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE)
                            .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                            .addGroup(contentPaneLayout.createParallelGroup()
                                .addComponent(button3)
                                .addComponent(button2))
                            .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(scrollPane2, GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE)))
                    .addContainerGap())
        );
        contentPaneLayout.setVerticalGroup(
            contentPaneLayout.createParallelGroup()
                .addGroup(contentPaneLayout.createSequentialGroup()
                    .addContainerGap()
                    .addGroup(contentPaneLayout.createParallelGroup()
                        .addGroup(contentPaneLayout.createSequentialGroup()
                            .addGap(37, 37, 37)
                            .addComponent(button2, GroupLayout.PREFERRED_SIZE, 45, GroupLayout.PREFERRED_SIZE)
                            .addGap(18, 18, 18)
                            .addComponent(button3, GroupLayout.PREFERRED_SIZE, 45, GroupLayout.PREFERRED_SIZE)
                            .addGap(0, 395, Short.MAX_VALUE))
                        .addComponent(scrollPane1)
                        .addComponent(scrollPane2, GroupLayout.Alignment.TRAILING))
                    .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(scrollPane3, GroupLayout.DEFAULT_SIZE, 111, Short.MAX_VALUE)
                    .addContainerGap())
        );
        pack();
        setLocationRelativeTo(getOwner());
        // JFormDesigner - End of component initialization  //GEN-END:initComponents  @formatter:on
    }

    // JFormDesigner - Variables declaration - DO NOT MODIFY  //GEN-BEGIN:variables  @formatter:off
    // Generated using JFormDesigner Evaluation license - Wenchong Xu
    private JScrollPane scrollPane1;
    private JTextArea TextArea;
    private JScrollPane scrollPane2;
    private JTextArea Ccode;
    private JButton button2;
    private JButton button3;
    private JScrollPane scrollPane3;
    private JTextArea Result;
    // JFormDesigner - End of variables declaration  //GEN-END:variables  @formatter:on

    public void Parse() throws IOException {
//    	System.out.println(sout);
        File inFile = new File("testfile.txt");
        File lexerFile = new File("lexer.txt");
        File parserFile = new File("parser.txt");
        File astFile = new File("ast.json");
        File codeFile = new File("code.c");

        FileWriter inputWriter = new FileWriter(inFile);
        inputWriter.write(TextArea.getText());

        inputWriter.flush();
        inputWriter.close();

        FileDeal fileDeal = new FileDeal(inFile);
        try {
            fileDeal.readFile();
        } catch (IOException e) {
            System.out.println("IO error");
        }
        String procedure = fileDeal.getUnionLines();

        //词法分析
        Lexer lexer = new Lexer(procedure);
        lexer.Execute();
        ArrayList<Word> words = lexer.getWords();

        FileWriter lexerWriter = new FileWriter(lexerFile);

        for (Word word: words) {
            lexerWriter.write(word.toString() + "\n");
        }

        lexerWriter.flush();
        lexerWriter.close();

        Parser parser = new Parser(words);
        Program program = (Program) parser.Execute();

        FileWriter parserWriter = new FileWriter(parserFile);
        parserWriter.write(program.toTreeString(0));

        parserWriter.flush();
        parserWriter.close();

        //语义分析
        ast.Program programAst = (ast.Program) program.toAst();
        FileWriter astWriter = new FileWriter(astFile);
        astWriter.write(programAst.toJsonString());

        astWriter.flush();
        astWriter.close();

        //代码生成
        astPreprocessContext.getContext();
        programAst.preprocess(null);
        System.out.println(astPreprocessContext.toDebugString());
        FileWriter codeWriter = new FileWriter(codeFile);

        String code = programAst.toString();
        Ccode.setText(code);

        codeWriter.write(code);

        codeWriter.flush();
        codeWriter.close();
    }

    public void compileWithGCC() {
    	System.out.println();
//    	sout
        try {
            ProcessBuilder processBuilder = new ProcessBuilder("gcc", "code.c");
            Process process = processBuilder.start();
            int exitCode = process.waitFor();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void executeExecutable() {
        try {
            String inputText = Result.getText();
            String command;

            File inputFile = new File("input.txt");
            FileWriter inputWriter = new FileWriter(inputFile);
            inputWriter.write(inputText);

            inputWriter.flush();
            inputWriter.close();

            ProcessBuilder processBuilder = new ProcessBuilder("a.exe");
            processBuilder.redirectInput(inputFile);
            Process process = processBuilder.start();

            printProcessOutput(process.getInputStream());

            int exitCode = process.waitFor();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void printProcessOutput(java.io.InputStream inputStream) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String result = "";
        String line;
        while ((line = reader.readLine()) != null) {
            result += line + "\n";
        }
        Result.setText(result);
    }
}
